package com.seednia.module.core.resource.ui.web;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.seednia.foundation.framework.service.AbstractWebRequestController;
import com.seednia.foundation.framework.service.RequestContext;
import com.seednia.foundation.framework.service.ServiceContainer;
import com.seednia.foundation.framework.service.ServiceException;
import com.seednia.foundation.framework.util.RecordUtils;
import com.seednia.module.core.config.dto.Constants;
import com.seednia.module.core.config.dto.SettingDto;
import com.seednia.module.core.config.service.IConfigService;
import com.seednia.module.core.resource.dto.MediaDto;
import com.seednia.module.core.resource.dto.ResourceCriteria;
import com.seednia.module.core.resource.service.IMediaService;

@Controller
public class MediaController extends AbstractWebRequestController {
	
	private IMediaService service = null;
	
	private IConfigService configService = null;
	
	public MediaController() 
	{
	}
	
	public IConfigService getConfigService() {
		if (this.configService == null) {
			configService = ServiceContainer.getInstance().getByType(IConfigService.class);
		}
		return configService;
	}
	public void setConfigService(IConfigService configService) {
		this.configService = configService;
	}


	@RequestMapping(value="/image/{sid}/{filename}", method = RequestMethod.GET)
	public ResponseEntity<byte[]> getImage( @PathVariable(value="sid") long sid
			, @PathVariable(value="filename") String filename // dummy
			, @RequestParam(value="w", required=false) Integer width
			, @RequestParam(value="h", required=false) Integer height, HttpServletRequest request) 
			throws IOException 
	{
		RequestContext reqCtx = super.createRequestContext(request);
		MediaDto mediaDto = null;
		if ( RecordUtils.isSidPositive(sid)) {
			ResourceCriteria criteria = new ResourceCriteria(sid);
			try {
				mediaDto = this.getService().getMedia(reqCtx, criteria);
			} catch (ServiceException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else {
			mediaDto = new MediaDto();
			SettingDto dirRoot = getConfigService().getSystemSetting(Constants.SETTING_SITE_FILE_DIR);
			mediaDto.setRepositoryUri(dirRoot.getValue());
			mediaDto.setFileName(filename);
			mediaDto.setContentType(URLConnection.guessContentTypeFromName(filename));
		}

		File file = this.getService().fileFromRecord(mediaDto);
		
		InputStream fileIs = new BufferedInputStream(new FileInputStream(file));
		//URLConnection.guessContentTypeFromStream(fileIs);
		
		byte[] bytes = null;
		if (width != null || height!= null) {
			int resizeWidth = Integer.MAX_VALUE;
			int resizeHeight = Integer.MAX_VALUE;
			if (width != null)
				resizeWidth = width.intValue();
			if (height != null)
				resizeHeight = height.intValue();
			BufferedImage img = imageResize(fileIs, resizeWidth, resizeHeight);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ImageIO.write(img, "jpg", baos);
			bytes = baos.toByteArray();
		} else {
			bytes = IOUtils.toByteArray(fileIs);
		}
		
		MediaType mediaType = MediaType.valueOf(mediaDto.getContentType());
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(mediaType);
		headers.setContentLength(bytes.length);

		return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.CREATED);
	}

	/*
	@RequestMapping(value="/get", method = RequestMethod.GET)
	public ResponseEntity<byte[]> getFile(@RequestParam("type") String type, @RequestParam("fileId") String fileId
			, HttpServletRequest request) 
			throws IOException 
	{
		
		FileDto fileDto = this.getService().getFile(fileId);

		SettingDto dirRoot;
		dirRoot = getConfigService().getSystemSetting(SETTING_DIR_ROOT);

		File file = new File(dirRoot.getValue() + "/"+fileDto.getName());
		
		InputStream fileIs = new BufferedInputStream(new FileInputStream(file));
		byte[] bytes = IOUtils.toByteArray(fileIs); 
		
		MediaType mediaType = MediaType.valueOf(fileDto.getContentType());
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(mediaType);
		headers.setContentLength(file.length());

		return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.CREATED);
	}*/
	

	public IMediaService getService() {
		if (service == null) {
			service = ServiceContainer.getInstance().getByType(IMediaService.class);
		}
		return service;
	}

	public void setservice(IMediaService service) {
		this.service = service;
	}

	///
	

	
	public BufferedImage imageResize(InputStream input, int width, int height) throws IOException
	{
		BufferedImage originalImage = ImageIO.read(input);
		
		Dimension originalDim = new Dimension(originalImage.getWidth(), originalImage.getHeight()); 
		Dimension boundaryDim = new Dimension(width, height); 
		Dimension scaledDim = getScaledDimension(originalDim, boundaryDim);
		
		BufferedImage resizedImage = new BufferedImage( (int)scaledDim.getWidth(), (int)scaledDim.getHeight(), originalImage.getType());
	    Graphics2D g = resizedImage.createGraphics();
	    g.drawImage(originalImage, 0, 0, (int)scaledDim.getWidth(), (int)scaledDim.getHeight(), null);
	    g.dispose();

	    return resizedImage;
	    
	}
	
	public static Dimension getScaledDimension(Dimension imgSize, Dimension boundary) 
	{
	    double new_width = imgSize.getWidth();
	    double new_height = imgSize.getHeight();

	    // first check if we need to scale width
	    if (imgSize.getWidth() > boundary.getWidth()) {
	        //scale width to fit
	        new_width = boundary.getWidth();
	        //scale height to maintain aspect ratio
	        new_height = imgSize.getHeight() * boundary.getWidth() / imgSize.getWidth();
	    }

	    // then check if we need to scale even with the new height
	    if (imgSize.getHeight() > boundary.getHeight()) {
	        //scale height to fit instead
	        new_height = boundary.getHeight();
	        //scale width to maintain aspect ratio
	        new_width = imgSize.getWidth() * boundary.getHeight() /imgSize.getHeight();
	    }

	    return new Dimension( (int)new_width, (int)new_height);
	}
}
